package com.ztomorrow.ying_cun_plus.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.ztomorrow.ying_cun_plus.dao.mapper.BookInfoMapper;
import com.ztomorrow.ying_cun_plus.dao.mapper.FriendLinkMapper;
import com.ztomorrow.ying_cun_plus.dao.mapper.HomeBookMapper;
import com.ztomorrow.ying_cun_plus.dao.po.BookInfo;
import com.ztomorrow.ying_cun_plus.dao.po.HomeBook;
import com.ztomorrow.ying_cun_plus.dao.po.HomeFriendLink;
import com.ztomorrow.ying_cun_plus.dto.resp.HomeBookRespDto;
import com.ztomorrow.ying_cun_plus.dto.resp.HomeFriendLinkRespDto;
import com.ztomorrow.ying_cun_plus.service.HomeService;
import com.ztomorrow.ying_cun_plus.utils.CacheUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

import static com.ztomorrow.ying_cun_plus.constant.front.CacheConstant.*;

@Service
@RequiredArgsConstructor
public class HomeServiceImpl implements HomeService {

    private final CacheUtils cacheUtils;
    private final HomeBookMapper homeBookMapper;
    private final BookInfoMapper bookInfoMapper;
    private final FriendLinkMapper friendLinkMapper;

    @Override
    public List<HomeBookRespDto> listHomeBooks() {
        List<HomeBookRespDto> cache = cacheUtils.getCache(
                obj -> BeanUtil.copyProperties(obj, HomeBookRespDto.class),
                CAFFEINE_HOME_BOOK, REDIS_HOME_BOOK,
                jsonStr -> JSONUtil.toBean(jsonStr, HomeBookRespDto.class));
        if (cache != null) return cache;
        // 未命中，从数据库查询
        List<HomeBook> list = new LambdaQueryChainWrapper<>(homeBookMapper)
                .orderByAsc(HomeBook::getSort)
                .list();
        // 健壮性判断
        if (list.isEmpty()) {
            return Collections.emptyList();
        }
        // 返回数据，并保存缓存
        List<BookInfo> bookInfos = new LambdaQueryChainWrapper<>(bookInfoMapper)
                .in(BookInfo::getId, list.stream().map(HomeBook::getBookId).toList())
                .list();
        Map<Long, BookInfo> bookInfoMap = bookInfos.stream()
                .collect(Collectors.toMap(BookInfo::getId, Function.identity()));
        List<HomeBookRespDto> homeBookRespDtOs = BeanUtil.copyToList(list, HomeBookRespDto.class);
        homeBookRespDtOs.forEach(v -> {
            BookInfo bookInfo = bookInfoMap.get(v.getBookId());
            v.setBookName(bookInfo.getBookName());
            v.setPicUrl(bookInfo.getPicUrl());
            v.setAuthorName(bookInfo.getAuthorName());
            v.setBookDesc(bookInfo.getBookDesc());
        });
        cacheUtils.saveCache(homeBookRespDtOs,
                CAFFEINE_HOME_BOOK, REDIS_HOME_BOOK, REDIS_HOME_BOOK_TTL,
                JSONUtil::toJsonStr);
        return homeBookRespDtOs;
    }

    @Override
    public List<HomeFriendLinkRespDto> listHomeFriendLinks() {
        List<HomeFriendLinkRespDto> cache = cacheUtils.getCache(
                obj -> BeanUtil.copyProperties(obj, HomeFriendLinkRespDto.class),
                CAFFEINE_HOME_FRIEND_LINK, REDIS_HOME_FRIEND_LINK,
                jsonStr -> JSONUtil.toBean(jsonStr, HomeFriendLinkRespDto.class));
        if (cache != null) return cache;
        // 从友情链接表中查询出友情链接列表
        List<HomeFriendLinkRespDto> list = new LambdaQueryChainWrapper<>(friendLinkMapper)
                .orderByAsc(HomeFriendLink::getSort)
                .list()
                .stream()
                .map(v -> {
                    HomeFriendLinkRespDto respDto = new HomeFriendLinkRespDto();
                    respDto.setLinkName(v.getLinkName());
                    respDto.setLinkUrl(v.getLinkUrl());
                    return respDto;
                }).toList();
        cacheUtils.saveCache(list,
                CAFFEINE_HOME_FRIEND_LINK, REDIS_HOME_FRIEND_LINK, REDIS_FRIEND_LINK_TTL,
                JSONUtil::toJsonStr);
        return list;
    }
}
